﻿using SD.IOC.Core.Mediators;
using SD.Toolkits.Excel;
using SlamDunk.MES.DataDrive.Bussiness.Models.PlanContext;
using SlamDunk.MES.DataDrive.Common;
using SlamDunk.MES.DataDrive.Common.Attributes;
using SlamDunk.MES.IAppService.DTOs.Inputs;
using SlamDunk.MES.IAppService.DTOs.Outputs.PlanContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.ValueObjects.Enums;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SlamDunk.MES.DataDrive.Bussiness.Importers
{
    /// <summary>
    /// 导入计划
    /// </summary>
    [DataTag(15, "计划数据", "MES计划数据", DataDriveConfig.RealgoalName, DataDriveConfig.RealgoalConnectionStrings)]
    public class ImportPlan
    {
        #region # 导入销售订单 —— void ImportSaleOrders()
        /// <summary>
        /// 导入销售订单
        /// </summary>
        [DataTag("导入销售订单")]
        public void ImportSaleOrders()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IResourceContract resourceContract = ResolveMediator.Resolve<IResourceContract>();
            IPlanContract planContract = ResolveMediator.Resolve<IPlanContract>();
            SaleOrder[] saleOrders = ExcelReader.ReadFile<SaleOrder>(SystemConfig.InitalForPlanDataPath, "销售订单");
            SaleOrderDetail[] saleOrderDetails = ExcelReader.ReadFile<SaleOrderDetail>(SystemConfig.InitalForPlanDataPath, "销售订单明细");

            IGrouping<string, SaleOrderDetail>[] saleOrderDetailGroups = saleOrderDetails.GroupBy(x => x.销售订单编号).ToArray();

            if (ImportCacheData.EnterpriseInfos == null)
            {
                ImportCacheData.EnterpriseInfos = resourceContract.GetEnterprisesByPage(null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.MaterialInfos == null)
            {
                ImportCacheData.MaterialInfos = resourceContract.GetMaterialsByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            foreach (SaleOrder saleOrder in saleOrders)
            {
                IGrouping<string, SaleOrderDetail> saleOrderDetailGroup = saleOrderDetailGroups.Single(x => x.Key == saleOrder.销售订单编号);

                IList<SaleOrderDetailParam> detailParams = new List<SaleOrderDetailParam>();
                foreach (SaleOrderDetail saleOrderDetail in saleOrderDetailGroup)
                {
                    Guid productId = ImportCacheData.MaterialInfos.Single(x => x.Number == saleOrderDetail.产品编号).Id;

                    SaleOrderDetailParam detailParam = new SaleOrderDetailParam
                    {
                        productId = productId,
                        quantity = saleOrderDetail.数量,
                        productionBatchNo = saleOrderDetail.生产批号,
                        sort = saleOrderDetail.排序,
                        description = saleOrderDetail.描述
                    };
                    detailParams.Add(detailParam);
                }

                Guid customerId = ImportCacheData.EnterpriseInfos.Single(x => x.Number == saleOrder.客户编号).Id;

                planContract.CreateSaleOrder(saleOrder.销售订单编号, saleOrder.销售订单名称, customerId, DateTime.Parse(saleOrder.下单日期), DateTime.Parse(saleOrder.交付日期), saleOrder.描述, detailParams);
            }
        }
        #endregion

        #region # 审核销售订单 —— void CheckSaleOrders()
        /// <summary>
        /// 审核销售订单
        /// </summary>
        [DataTag("审核销售订单")]
        public void CheckSaleOrders()
        {
            IPlanContract planContract = ResolveMediator.Resolve<IPlanContract>();

            IEnumerable<SaleOrderInfo> saleOrderInfos = planContract.GetSaleOrdersByPage(null, null, null, null, CheckStatus.Unchecked, null, null, 1, int.MaxValue).Datas;
            foreach (SaleOrderInfo saleOrderInfo in saleOrderInfos)
            {
                planContract.SubmitSaleOrder(saleOrderInfo.Id);
                planContract.CheckSaleOrder(saleOrderInfo.Id, true, "审核通过");
            }
        }
        #endregion

        #region # 导入生产计划 —— void ImportProductionPlan()
        /// <summary>
        /// 导入生产计划
        /// </summary>
        [DataTag("导入生产计划")]
        public void ImportProductionPlan()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IResourceContract resourceContract = ResolveMediator.Resolve<IResourceContract>();
            IDefinitionContract definitionContract = ResolveMediator.Resolve<IDefinitionContract>();
            IPlanContract planContract = ResolveMediator.Resolve<IPlanContract>();
            ProductionPlan[] productionPlans = ExcelReader.ReadFile<ProductionPlan>(SystemConfig.InitalForPlanDataPath, "生产计划");

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            if (ImportCacheData.MaterialInfos == null)
            {
                ImportCacheData.MaterialInfos = resourceContract.GetMaterialsByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.BomInfos == null)
            {
                ImportCacheData.BomInfos = definitionContract.GetBomsByPage(null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }

            IList<SaleOrderInfo> saleOrderInfos = planContract.GetSaleOrdersByPage(null, null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();

            foreach (ProductionPlan productionPlan in productionPlans)
            {
                Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == productionPlan.工厂模型编号)?.Id;
                Guid productId = ImportCacheData.MaterialInfos.Single(x => x.Number == productionPlan.产品编号).Id;
                Guid bomId = ImportCacheData.BomInfos.Single(x => x.Number == productionPlan.物料清单编号).Id;
                SaleOrderInfo saleOrderInfo = string.IsNullOrWhiteSpace(productionPlan.销售订单编号)
                    ? null
                    : saleOrderInfos.Single(x => x.Number == productionPlan.销售订单编号);

                planContract.CreateProductionPlan(productionPlan.生产计划编号, productionPlan.生产计划名称, productionPlan.生产批号, DateTime.Parse(productionPlan.预期开始时间), DateTime.Parse(productionPlan.预期结束时间), DateTime.Parse(productionPlan.最早开始时间), DateTime.Parse(productionPlan.最晚结束时间), productId, bomId, productionPlan.预期毛产量, productionPlan.预期净产量, saleOrderInfo?.Id, facilityId, productionPlan.优先级, productionPlan.描述);
            }
        }
        #endregion

        #region # 导入生产计划物料需求 —— void ImportProductionMaterialAsks()
        /// <summary>
        /// 导入生产计划物料需求
        /// </summary>
        [DataTag("导入生产计划物料需求")]
        public void ImportProductionMaterialAsks()
        {
            IDefinitionContract definitionContract = ResolveMediator.Resolve<IDefinitionContract>();
            IPlanContract planContract = ResolveMediator.Resolve<IPlanContract>();
            IEnumerable<ProductionPlanInfo> productionPlanInfos = planContract.GetProductionPlansByPage(null, null, null, null, null, null, null, null, null, 1, int.MaxValue).Datas;

            foreach (ProductionPlanInfo productionPlanInfo in productionPlanInfos)
            {
                IDictionary<Guid, decimal> materialQuantities = definitionContract.CalculateMaterialAsks(productionPlanInfo.BomId, productionPlanInfo.ExpGrossQuantity);
                IList<ProductionMaterialAskParam> materialAskParams = new List<ProductionMaterialAskParam>();
                foreach (KeyValuePair<Guid, decimal> kv in materialQuantities)
                {
                    ProductionMaterialAskParam materialAskParam = new ProductionMaterialAskParam
                    {
                        materialId = kv.Key,
                        quantity = kv.Value
                    };
                    materialAskParams.Add(materialAskParam);
                }

                planContract.SetProductionMaterialAsks(productionPlanInfo.Id, materialAskParams);
            }
        }
        #endregion

        #region # 审核/发布生产计划 —— void CheckProductionPlans()
        /// <summary>
        /// 审核/发布生产计划
        /// </summary>
        [DataTag("审核/发布生产计划")]
        public void CheckProductionPlans()
        {
            IPlanContract planContract = ResolveMediator.Resolve<IPlanContract>();

            IEnumerable<ProductionPlanInfo> productionPlanInfos = planContract.GetProductionPlansByPage(null, null, null, null, null, CheckStatus.Unchecked, null, null, null, 1, int.MaxValue).Datas;
            foreach (ProductionPlanInfo productionPlanInfo in productionPlanInfos)
            {
                planContract.SubmitProductionPlan(productionPlanInfo.Id);
                planContract.CheckProductionPlan(productionPlanInfo.Id, true, "审核通过");
                planContract.ReleaseProductionPlan(productionPlanInfo.Id);
            }
        }
        #endregion

        #region # 导入作业计划 —— void ImportExecutionPlan()
        /// <summary>
        /// 导入作业计划
        /// </summary>
        [DataTag("导入作业计划")]
        public void ImportExecutionPlan()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IResourceContract resourceContract = ResolveMediator.Resolve<IResourceContract>();
            IDefinitionContract definitionContract = ResolveMediator.Resolve<IDefinitionContract>();
            IPlanContract planContract = ResolveMediator.Resolve<IPlanContract>();
            ExecutionPlan[] executionPlans = ExcelReader.ReadFile<ExecutionPlan>(SystemConfig.InitalForPlanDataPath, "作业计划");

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            if (ImportCacheData.MaterialInfos == null)
            {
                ImportCacheData.MaterialInfos = resourceContract.GetMaterialsByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.ProcessInfos == null)
            {
                ImportCacheData.ProcessInfos = definitionContract.GetProcessesByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.BomInfos == null)
            {
                ImportCacheData.BomInfos = definitionContract.GetBomsByPage(null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }

            IList<ProductionPlanInfo> productionPlanInfos = planContract.GetProductionPlansByPage(null, null, null, null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            foreach (ExecutionPlan executionPlan in executionPlans)
            {
                Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == executionPlan.工厂模型编号)?.Id;
                Guid productId = ImportCacheData.MaterialInfos.Single(x => x.Number == executionPlan.产品编号).Id;
                Guid processId = ImportCacheData.ProcessInfos.Single(x => x.Number == executionPlan.工艺编号).Id;
                Guid bomId = ImportCacheData.BomInfos.Single(x => x.Number == executionPlan.物料清单编号).Id;
                ProductionPlanInfo productionPlanInfo = string.IsNullOrWhiteSpace(executionPlan.生产计划编号)
                    ? null
                    : productionPlanInfos.Single(x => x.Number == executionPlan.生产计划编号);

                planContract.CreateExecutionPlan(executionPlan.作业计划编号, executionPlan.作业计划名称, executionPlan.生产批号, DateTime.Parse(executionPlan.预期开始时间), DateTime.Parse(executionPlan.预期结束时间), DateTime.Parse(executionPlan.最早开始时间), DateTime.Parse(executionPlan.最晚结束时间), productId, processId, bomId, executionPlan.预期毛产量, executionPlan.预期净产量, productionPlanInfo?.Id, facilityId, executionPlan.优先级, executionPlan.描述);
            }

        }
        #endregion

        #region # 导入作业计划物料需求 —— void ImportExecutionMaterialAsks()
        /// <summary>
        /// 导入作业计划物料需求
        /// </summary>
        [DataTag("导入作业计划物料需求")]
        public void ImportExecutionMaterialAsks()
        {
            IDefinitionContract definitionContract = ResolveMediator.Resolve<IDefinitionContract>();
            IPlanContract planContract = ResolveMediator.Resolve<IPlanContract>();
            IEnumerable<ExecutionPlanInfo> executionPlanInfos = planContract.GetExecutionPlansByPage(null, null, null, null, null, null, null, null, null, null, null, null, 1, int.MaxValue).Datas;

            foreach (ExecutionPlanInfo executionPlanInfo in executionPlanInfos)
            {
                IDictionary<Guid, decimal> materialQuantities = definitionContract.CalculateMaterialAsks(executionPlanInfo.BomId, executionPlanInfo.ExpGrossQuantity);
                IList<ExecutionMaterialAskParam> materialAskParams = new List<ExecutionMaterialAskParam>();
                foreach (KeyValuePair<Guid, decimal> kv in materialQuantities)
                {
                    ExecutionMaterialAskParam materialAskParam = new ExecutionMaterialAskParam
                    {
                        materialId = kv.Key,
                        quantity = kv.Value
                    };
                    materialAskParams.Add(materialAskParam);
                }

                planContract.SetExecutionMaterialAsks(executionPlanInfo.Id, materialAskParams);
            }
        }
        #endregion

        #region # 审核/发布作业计划 —— void CheckExecutionPlans()
        /// <summary>
        /// 审核/发布作业计划
        /// </summary>
        [DataTag("审核/发布作业计划")]
        public void CheckExecutionPlans()
        {
            IPlanContract planContract = ResolveMediator.Resolve<IPlanContract>();

            IEnumerable<ExecutionPlanInfo> executionPlanInfos = planContract.GetExecutionPlansByPage(null, null, null, null, null, null, CheckStatus.Unchecked, null, null, null, null, null, 1, int.MaxValue).Datas;
            foreach (ExecutionPlanInfo executionPlanInfo in executionPlanInfos)
            {
                planContract.SubmitExecutionPlan(executionPlanInfo.Id);
                planContract.CheckExecutionPlan(executionPlanInfo.Id, true, "审核通过");
                planContract.ReleaseExecutionPlan(executionPlanInfo.Id);
            }
        }
        #endregion
    }
}
